package com.yhy.admin.action;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.yhy.admin.dto.MenuDTO;
import com.yhy.admin.service.MenuLanService;
import com.yhy.admin.service.mng.MenuMngService;
import com.yhy.admin.service.mng.SysRoleMngService;
import com.yhy.admin.vo.MenuBuildVo;
import com.yhy.admin.vo.MenuLanVO;
import com.yhy.admin.vo.mng.MenuMngVO;
import com.yhy.common.action.BaseMngAction;
import com.yhy.common.constants.BusClassType;
import com.yhy.common.constants.BusMenuType;
import com.yhy.common.constants.BusPrivCode;
import com.yhy.common.dto.AppReturnMsg;
import com.yhy.common.dto.ReturnCode;
import com.yhy.common.intercept.LoginPermission;
import com.yhy.common.intercept.PreCheckPermission;
import com.yhy.common.utils.*;
import com.yhy.common.vo.SysUser;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping(value="/admin-service/api/menuMng", produces="application/json;charset=UTF-8")
public class MenuMngAction extends BaseMngAction<MenuDTO> {
    private static final Logger LOGGER = LoggerFactory.getLogger(MenuMngAction.class);

    @Autowired
    private MenuMngService menuMngService;
    @Autowired
    private SysRoleMngService sysRoleMngService;
    @Autowired
    private MenuLanService menuLanService;

    @Override
    protected MenuMngService getBaseService() {
        return menuMngService;
    }

    /**
     * 构建前端路由所需要的菜单
     * @return
     */
    @GetMapping(value = "/build")
    @ResponseBody
    @LoginPermission
    @ApiOperation(value="构建前端路由所需要的菜单", notes="构建前端路由所需要的菜单")
    public AppReturnMsg build(HttpServletRequest request, HttpServletResponse response) {
        SysUser sysUser = YhyUtils.getSysUser();

        Object cacheMenus = RedisUtil.get(ConstantUtil.MENU_PREFIX + sysUser.getSourceType() + sysUser.getUserAccount());
        if(cacheMenus != null) {
            return new AppReturnMsg(ReturnCode.SUCCESS_CODE.getCode(),null,cacheMenus,null);
        }
        List<MenuMngVO> allMenus = getBaseService().findAllMenu(sysUser.getLanCode());
        List<MenuMngVO> privLeafMenu = null;
        if(sysUser.isSysAdmin()) {
            //系统管理员返回所有菜单
            privLeafMenu = allMenus;
        } else {
            Set<String> roleids = sysRoleMngService.findRoleByUserInfo(sysUser.getCpyCode(),sysUser.getUserAccount());
            if(roleids.isEmpty()) {
                return new AppReturnMsg(ReturnCode.SUCCESS_CODE.getCode(),null,Lists.newArrayList(),null);
            }
            boolean isCommonAdmin = false;
            List<MenuMngVO> privCodes = getBaseService().findMenuPrivByRoleids(roleids);
            for (MenuMngVO tmpVo : privCodes) {
                if(BusPrivCode.PRIV_COMMON_ADMIN.getVal().equals(tmpVo.getPrivCode())) {
                    //获取非系统管理员的所有菜单 为当前用户的权限菜单
                    isCommonAdmin = true;
                    break;
                }
            }
            if(isCommonAdmin) {
                privLeafMenu = getBaseService().findCommonAdminMenu(sysUser.getLanCode());
            } else {
                privLeafMenu = getBaseService().findMenuByRoleids(roleids,"0", sysUser.getLanCode());
            }
        }

        Map<String,MenuMngVO> allMenuSets = Maps.newHashMap();
        allMenus.stream().forEach(
                menuMngVO -> {
                    if(!BusMenuType.MENU_PRIV.getVal().equals(menuMngVO.getMenuType()))
                        allMenuSets.put(menuMngVO.getId(),menuMngVO);
                }
        );
        Set<String> parentPrivMenuIds = Sets.newHashSet();
        Set<String> allPrivMenuIds = Sets.newHashSet();
        for (MenuMngVO tmpVo : privLeafMenu) {
            if(!BusMenuType.MENU_PRIV.getVal().equals(tmpVo.getMenuType())) {
                setParentPrivMenuIds(parentPrivMenuIds,allMenuSets, tmpVo.getId());
                allPrivMenuIds.add(tmpVo.getId());
            }
        }

        for (MenuMngVO tmpVo : allMenus) {
            if(parentPrivMenuIds.contains(tmpVo.getId()) && !allPrivMenuIds.contains(tmpVo.getId())) {
                privLeafMenu.add(tmpVo);
            }
        }
        List<MenuMngVO> menuTree = menuMngService.buildMenuTree(privLeafMenu);
        List<MenuBuildVo> rtnTree = menuMngService.buildMenus(menuTree);
        /*ObjectMapper objectMapper = new ObjectMapper();
        String rtnStr = "";//JsonUtils.toJson(menuMngService.buildMenus(menuTree));
        try {
            rtnStr = objectMapper.writeValueAsString(menuMngService.buildMenus(menuTree));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }*/
        List<HashMap> rtnMap = JsonUtils.tranList(rtnTree,HashMap.class);
        RedisUtil.set(ConstantUtil.MENU_PREFIX + sysUser.getSourceType() + sysUser.getUserAccount(),rtnMap);
        return new AppReturnMsg(ReturnCode.SUCCESS_CODE.getCode(),null,rtnMap,null);
    }

    private void setParentPrivMenuIds(Set<String> parentPrivMenuIds, Map<String,MenuMngVO> allMenuSets, String menuId) {
        MenuMngVO tmpMenuVO = allMenuSets.get(menuId);
        if(tmpMenuVO != null && StringUtils.isNotBlank(tmpMenuVO.getParentId())) {
            if(!parentPrivMenuIds.contains(tmpMenuVO.getParentId())) {
                parentPrivMenuIds.add(tmpMenuVO.getParentId());
            }
            MenuMngVO parentMenuVO = allMenuSets.get(tmpMenuVO.getParentId());
            setParentPrivMenuIds(parentPrivMenuIds,allMenuSets,parentMenuVO.getId());
        }
    }

    @RequestMapping(value="/getAllWorkflowMenusTree",method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value="获取所有具有工作流功能的菜单", notes="获取所有具有工作流功能的菜单")
    public AppReturnMsg getAllWorkflowMenusTree(HttpServletRequest request, HttpServletResponse response) {

        List<MenuMngVO> allMenus =   getBaseService().findAllMenu(YhyUtils.getSysUser().getLanCode());

        Map<String,MenuMngVO> allMenuSets = Maps.newHashMap();
        List<MenuMngVO> allWorkflowMenuSets = Lists.newArrayList();

        allMenus.stream().forEach (
            menuMngVO -> {
                allMenuSets.put(menuMngVO.getId(),menuMngVO);
                if("1".equals(menuMngVO.getIsWorkflow()) && StringUtils.isNotBlank(menuMngVO.getModuleBusClass())) {
                    allWorkflowMenuSets.add(menuMngVO);
                }
            }
        );
        Set<String> parentPrivMenuIds = Sets.newHashSet();
        Set<String> allPrivMenuIds = Sets.newHashSet();
        for (MenuMngVO tmpVo : allWorkflowMenuSets) {
            setParentPrivMenuIds(parentPrivMenuIds,allMenuSets, tmpVo.getId());
            allPrivMenuIds.add(tmpVo.getId());
        }
        for (MenuMngVO tmpVo : allMenus) {
            if(parentPrivMenuIds.contains(tmpVo.getId()) && !allPrivMenuIds.contains(tmpVo.getId())) {
                allWorkflowMenuSets.add(tmpVo);
            }
        }

        List<MenuMngVO> tree = getBaseService().buildMenuTree(allWorkflowMenuSets);

        return new AppReturnMsg(ReturnCode.SUCCESS_CODE.getCode(),"",tree,null);
    }

    @RequestMapping(value="/getAllExtendMenu",method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value="获取所有扩展功能设置菜单", notes="获取所有扩展功能设置菜单")
    public AppReturnMsg getAllExtendMenu(HttpServletRequest request, HttpServletResponse response) {
        SysUser sysUser = YhyUtils.getSysUser();
        List<MenuMngVO> mngVOS = getBaseService().findCommonAdminMenu(sysUser.getLanCode());
        List<MenuMngVO> rntList = mngVOS.stream().filter(tmpvo ->
                        StringUtils.isNotBlank(tmpvo.getModuleBusClass())
                        && BusClassType.getInstByVal(tmpvo.getModuleBusClass()).getExtendMng())
                .collect(Collectors.<MenuMngVO>toList());
        return new AppReturnMsg(ReturnCode.SUCCESS_CODE.getCode(),"",rntList,null);
    }

    @RequestMapping(value="/getAllMenusTree",method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value="获取所有菜单", notes="获取所有菜单")
    public AppReturnMsg getAllMenusTree(HttpServletRequest request, HttpServletResponse response) {
        SysUser sysUser = YhyUtils.getSysUser();
        List<MenuMngVO> mngVOS = getBaseService().findAllValidRecord(sysUser.getLanCode(), sysUser.isSysAdmin() ? null : "0");
        List<MenuMngVO> tree = getBaseService().buildMenuTree(mngVOS);
        return new AppReturnMsg(ReturnCode.SUCCESS_CODE.getCode(),"",JsonUtils.tranList(tree,HashMap.class),null);
    }

    @RequestMapping(value="/getMenuLanByMenuId",method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value="根据主ID获取菜单语言", notes="根据主ID获取菜单语言")
    public AppReturnMsg getMenuLanByMenuId(@RequestParam(value = "menuId",required = true)String menuId, HttpServletRequest request, HttpServletResponse response) {
        List<MenuLanVO> menuLanVOS = menuLanService.findByMenuId(menuId);
        return new AppReturnMsg(ReturnCode.SUCCESS_CODE.getCode(),"",menuLanVOS,null);
    }

    @Override
    protected void afterLoadDataInfo(MenuDTO baseDTO,AppReturnMsg returnMsg ) {
        super.afterLoadDataInfo(baseDTO,returnMsg);
        List<MenuMngVO> rtnList = baseDTO.getRtnList();
        List<MenuMngVO> tree = getBaseService().buildMenuTree(rtnList);
        returnMsg.setData(tree);
    }

    @PreCheckPermission(roles = {"SYS_ADMIN"})
    @RequestMapping(value="/toAdd",method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value="新增操作", notes="新增操作")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "baseDTO", value = "提交对象ID", required = true, dataTypeClass = MenuDTO.class)
    })
    public AppReturnMsg toAdd(HttpServletRequest request, HttpServletResponse response, @RequestBody MenuDTO baseDTO) {
        return super.toAddCommon(request, response, baseDTO);
    }

    @PreCheckPermission(roles = {"SYS_ADMIN"})
    @RequestMapping(value="/toCopy",method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value="复制操作", notes="复制操作")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "baseDTO", value = "提交对象ID", required = true, dataTypeClass = MenuDTO.class)
    })
    public AppReturnMsg toCopy(HttpServletRequest request, HttpServletResponse response, @RequestBody MenuDTO baseDTO) {
        return super.toCopyCommon(request, response, baseDTO);
    }

    @Override
    protected void beforeOfSaveProcess(MenuDTO baseDTO) {
        super.beforeOfSaveProcess(baseDTO);
    }

    @PreCheckPermission(roles = {"SYS_ADMIN"})
    @RequestMapping(value="/doSave",method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value="保存", notes="保存操作")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "baseDTO", value = "数据传输对象", required = true, dataType = "MenuDTO")
    })
    public AppReturnMsg doSave(HttpServletRequest request, HttpServletResponse response, @RequestBody MenuDTO baseDTO) {
        return super.doSaveCommon(request, response, baseDTO);
    }

    @PreCheckPermission(roles = {"SYS_ADMIN"})
    @RequestMapping(value="/loadData",method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value="查询数据", notes="查询操作")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "baseDTO", value = "数据传输对象", required = true, dataType = "MenuDTO")
    })
    public AppReturnMsg loadData(HttpServletRequest request, HttpServletResponse response, @RequestBody MenuDTO baseDTO) {
        SysUser sysUser = YhyUtils.getSysUser();
        sysUser.setCpyCode(null);
        baseDTO.setSysUser(sysUser);
        return super.loadDataCommon(request, response, baseDTO);
    }

    @PreCheckPermission(roles = {"SYS_ADMIN"})
    @RequestMapping(value="/doDelete",method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value="删除", notes="删除操作")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "baseDTO", value = "删除", required = true, dataType = "MenuDTO")
    })
    public AppReturnMsg doDelete(HttpServletRequest request, HttpServletResponse response, @RequestBody MenuDTO baseDTO) {
        return super.doDeleteCommon(request, response, baseDTO);
    }
}
